#include "mb_queue.h"

/**
 * @brief 实现队列初始化函数
*/
MB_Status xMB_QueueInit(MB_Queue* pQueue, size_t maxQueueSize)
{
    // 判断要初始化的队列的指针是否为空
    MB_CHECK_POINTER(pQueue);

    // 初始化队列
    pQueue->maxSize = maxQueueSize;
    pQueue->pData = (uint8_t*)malloc(maxQueueSize * sizeof(uint8_t));
    pQueue->head = 0;
    pQueue->tail = 0;
    pQueue->currentSize = 0;

    return MB_OK;
}

/**
 * @brief 实现入队函数
*/
MB_Status xMB_QueuePush(MB_Queue* pQueue, uint8_t data)
{
    MB_Status result;
    uint8_t isQueueFull;
    
    MB_CHECK_POINTER(pQueue);
    MB_TEST_COND(pQueue->maxSize != 0)

    // 根据队列的状态来确定返回值
    if (MB_OK == xMB_QueueIsFull(pQueue, &isQueueFull))
    {
        if (isQueueFull)
        {
            // 栈满了，但是仍然可以入队，只是会顶掉最开始入队的元素
            result =  MB_BUSY;
        }
        else
        {
            // 没满
            result = MB_OK;
        }
    }
    else 
    {
        // 无法获取队列的状态
        result = MB_ERROR;
    }

    // 元素入队
    pQueue->pData[pQueue->head] = data;
    pQueue->head++;
    pQueue->head %= pQueue->maxSize;

    if (!isQueueFull)
        pQueue->currentSize++;

    return result;
}

/**
 * @brief 实现出队函数
*/
MB_Status xMB_QueuePop(MB_Queue* pQueue, uint8_t *pData)
{
    MB_Status result;
    uint8_t isQueueEmpty;

    MB_CHECK_POINTER(pQueue);
    MB_CHECK_POINTER(pData);

    if (MB_OK == xMB_QueueIsEmpty(pQueue, &isQueueEmpty)) 
    {
        if (isQueueEmpty) 
        {
            // 队列为空，不能出队
            result = MB_ERROR;
        }
        else
        {
            *pData = pQueue->pData[pQueue->tail];
            pQueue->tail++;
            pQueue->currentSize--;
            result = MB_OK;
        }
    }
    else
    {
        // 无法获取队列状态
        result = MB_ERROR;
    }

    return result;
}

/**
 * @brief 实现判断队列是否已满的函数
*/
MB_Status xMB_QueueIsFull(MB_Queue* pQueue, uint8_t *pIsFull)
{
    MB_CHECK_POINTER(pQueue);
    MB_CHECK_POINTER(pIsFull);

    *pIsFull = (pQueue->maxSize == pQueue->currentSize);
    return MB_OK;
}

/**
 * @brief 实现判断队列是否为空的函数
*/
MB_Status xMB_QueueIsEmpty(MB_Queue* pQueue, uint8_t *pIsEmpty)
{
    MB_CHECK_POINTER(pQueue);
    MB_CHECK_POINTER(pIsEmpty);

    *pIsEmpty = (0 == pQueue->currentSize);
    return MB_OK;
}

/**
 * @brief 实现获取队列队头元素的函数
*/
MB_Status cMB_QueueGetHeadElement(MB_Queue* pQueue, uint8_t* pData)
{
    MB_CHECK_POINTER(pQueue);
    MB_CHECK_POINTER(pData);

    if (pQueue->currentSize == 0) {
        return MB_ERROR;
    }

    *pData = pQueue->pData[pQueue->head - 1];
    return MB_OK;
}

/**
 * @brief 实现获取队列队尾元素的函数
*/
MB_Status cMB_QueueGetTailElement(MB_Queue* pQueue, uint8_t* pData)
{
    MB_CHECK_POINTER(pQueue);
    MB_CHECK_POINTER(pData);

    if (pQueue->currentSize == 0) {
        return MB_ERROR;
    }

    *pData = pQueue->pData[pQueue->tail];
    return MB_OK;
}

/**
 * @brief 实现获取队列最大长度的函数
*/
MB_Status lMB_QueueGetMaxSize(MB_Queue* pQueue, size_t* pMaxSize)
{
    MB_CHECK_POINTER(pQueue);
    MB_CHECK_POINTER(pMaxSize);

    *pMaxSize = pQueue->maxSize;
    return MB_OK;
}

/**
 * @brief 实现获取队列当前长度的函数
*/
MB_Status lMB_QueueGetCurrentSize(MB_Queue* pQueue, size_t *pCurrentSize)
{
    MB_CHECK_POINTER(pQueue);
    MB_CHECK_POINTER(pCurrentSize);

    *pCurrentSize = pQueue->currentSize;
    return MB_OK;
}